package com.molichuxing.framework.utils;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 解析xml工具类
 *
 * @author shichaomeng
 */
public class XmlUtil {
	/**
	 * 解析xml返回跟标签
	 *
	 * @param xmlStr
	 * @return
	 */
	public static Element parserXml(String xmlStr) {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		Element root = null;
		try {
			db = dbf.newDocumentBuilder();
			Document dom = db.parse(new ByteArrayInputStream(xmlStr.getBytes("UTF-8")));
			root = dom.getDocumentElement();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return root;
	}

	/**
	 * 解析请求参数
	 *
	 * @param root
	 * @param childName
	 * @return
	 */
	public static String getChildValueByName(Element root, String childName) {
		NodeList nl = root.getChildNodes();
		String value = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (childName.equals(node.getNodeName())) {
				value = "";
				try {
					value = node.getFirstChild().getNodeValue().trim();
				} catch (Exception e) {
					value = "";
				}
				break;
			}
		}
		return value;
	}

	/**
	 * 获取子标签
	 *
	 * @param root
	 * @param childName
	 * @return
	 */
	public static Element getChildElement(Element root, String childName) {
		NodeList list = root.getElementsByTagName(childName);
		Element item = (Element) list.item(0);
		return item;
	}

	/**
	 * 获取元素列表
	 *
	 * @param root
	 * @param rootName
	 * @param childName
	 * @return
	 */
	public static NodeList getNodeListByName(Element root, String rootName, String childName) {
		Element entityListElement = getChildElement(root, rootName);
		NodeList entitys = entityListElement.getElementsByTagName(childName);
		return entitys;
	}

	/**
	 * 创建XML标签
	 *
	 * @param tag
	 * @param data
	 * @return
	 */
	@NotNull
	public static String createXmlTag(String tag, String data) {
		StringBuffer sb = new StringBuffer();
		sb.append("<" + tag + ">").append(data == null ? "" : data).append("</" + tag + ">").append("\n");
		return sb.toString();
	}

	/**
	 * xml转换map
	 * 
	 * @param xmlStr
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> xmlToMap(String xmlStr) throws Exception {
		Map<String, String> result = null;
		InputStream is = null;
		try {
			result = new HashMap<String, String>();
			DocumentBuilder documentBuilder = newDocumentBuilder();
			is = new ByteArrayInputStream(xmlStr.getBytes("UTF-8"));
			org.w3c.dom.Document doc = documentBuilder.parse(is);
			doc.getDocumentElement().normalize();
			NodeList nodeList = doc.getDocumentElement().getChildNodes();
			for (int idx = 0; idx < nodeList.getLength(); ++idx) {
				Node node = nodeList.item(idx);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					org.w3c.dom.Element element = (org.w3c.dom.Element) node;
					result.put(element.getNodeName(), element.getTextContent());
				}
			}
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (Exception e) {
					is = null;
				}
			}
		}

		return result;
	}

	public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
		documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
		documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
		documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
		documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
		documentBuilderFactory.setXIncludeAware(false);
		documentBuilderFactory.setExpandEntityReferences(false);

		return documentBuilderFactory.newDocumentBuilder();
	}

	public static Document newDocument() throws ParserConfigurationException {
		return newDocumentBuilder().newDocument();
	}

}
